home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / others / justify.zip / JUSTIFY.C < prev    next >
C/C++ Source or Header  |  1993-12-17  |  8KB  |  253 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #include <ctype.h>
  6.  
  7. #define LINEMAX (512)
  8. #define WORDMAX (64)
  9.  
  10. #define INDENTED(string) (*string == ' ')
  11. #define BLANK(string) (*string == '\n')
  12. #define ZEROLEN(string) (*string == '\0')
  13. #define TEXT(string) (*string > ' ')    /* A cheat */
  14.  
  15. int columns, indent, body;    /* command line arguments */
  16. int dspace, dblank, iblank, hindent;     /* command line flags */
  17. int indpar, indbod, fullpar, nohyph, rright, wproc;
  18.  
  19. char line[LINEMAX];    /* Line being composed */
  20. char hword[WORDMAX]; /* word in hyphenation */
  21. int firstline;    /* composing first line */
  22.  
  23. void usage(void)
  24. {
  25.     fprintf(stderr, "\nUSAGE:\njustify columns [b][f][d][i][t][o][h][s][r][w] [indent] [body] <source >dest\n"
  26.                     "  b - input file paragraph is hanging indented\n"
  27.                     "  f - input file paragraph is fully indented\n"
  28.                     "  d - delete blank line after paragraph read\n"
  29.                     "  i - insert blank line after paragraph read\n"
  30.                     "  t - indent first paragraph lines by indent spaces\n"
  31.                     "  o - indent other paragraph lines by body spaces\n"
  32.                     "  h - remove hyphens across line boundaries\n"
  33.                     "  s - double space after . ? ! .\" ?\" or !\"\n"
  34.                     "  w - output for word processors\n"
  35.                     "  r - ragged right margin (otherwise full justification)\n");
  36.     exit(4);
  37. }
  38.  
  39. int trim(char *s) {  /* trim spaces from end of line */
  40.     char *end = s + strlen(s) - 2;
  41.  
  42.     while (s <= end && *end == ' ') end--;
  43.  
  44.     *++end = '\n';
  45.     *++end = '\0';
  46.  
  47.     return 1;    /* return success always */
  48. }
  49.  
  50.             
  51. void fill(char *s, int size) {
  52.     static int fromleft = 0;        /* alternate sides */
  53.     char *cp;
  54.     int blanks = size - strlen(s);
  55.  
  56.     fromleft++;
  57.  
  58.     if (strchr(s, ' ') == NULL) return;    /* cant justify single word line */
  59.  
  60.     if (fromleft & 1) {    /* insert from left */
  61.         while (blanks) {
  62.             cp = s;    /* start at left edge */
  63.             while (blanks) {
  64.                 while (*cp != ' ' && !ZEROLEN(cp)) cp++;    /* find a blank */
  65.                 if (ZEROLEN(cp)) break;    /* need another pass */
  66.                 memmove(cp+1, cp, strlen(cp)+1);    /* insert a space */
  67.                 while (*++cp == ' ');    /* skip past spaces */
  68.                 blanks--;
  69.             }
  70.         }
  71.     }
  72.     else { /* insert from right */
  73.         while (blanks) {
  74.             cp = s + strlen(s) - 1;    /* start at right edge */
  75.             while (blanks) {
  76.                 while (*cp != ' ' && cp >= s) cp--; /* find a blank */
  77.                 if (cp < s) break;    /* need another pass */
  78.                 memmove(cp+1, cp, strlen(cp)+1);  /* insert a space */
  79.                 while (*--cp == ' ');    /* skip past spaces */
  80.                 blanks--;
  81.             }
  82.         }
  83.     }
  84. }
  85.  
  86.  
  87. void emitword(char *s) {
  88.     int wlen = strlen(s);    /* length of this word */
  89.     int llen = firstline ? columns - indent : columns - body;    /*length of this line*/
  90.     int clen = strlen(line);    /* length of line so far */
  91.     int dbl = 0;
  92.  
  93.     if (!ZEROLEN(hword))    { /* combine hyphenated word */
  94.         if (nohyph) hword[strlen(hword)-1] = '\0';    /* remove hyphen */
  95.         strcat(hword, s);                /* concatenate pieces */
  96.         strcpy(s, hword);
  97.         wlen = strlen(s);
  98.         hword[0] = '\0';
  99.     }
  100.  
  101.     if (clen==0)    { /* first word in line */
  102.         strcpy(line,s);
  103.         return;
  104.     }
  105.     if (dspace && ((strchr(".?!", line[clen-1]) != NULL &&
  106.                     clen > 2 &&
  107.                     isalpha(line[clen-2]) &&
  108.                     (isalpha(line[clen-3]) || line[clen-1] != '.')) ||
  109.                    (line[clen-1] == '"' &&
  110.                     clen > 3 &&
  111.                     strchr(".?!", line[clen-2]) != NULL ))) {
  112.         /* guess we are at end of sentence */
  113.         dbl = 1;
  114.     }
  115.     if (wproc)    { /* special case Word Processor output */
  116.         printf("%s%s", line, dbl ? "  " : " ");    /* print previous word */
  117.         strcpy(line, s);
  118.         return;
  119.     }
  120.     if (wlen+clen+dbl+1 > llen)    { /* word won't fit */
  121.         int i = firstline ? indent : body;    /* line indentation */
  122.         while (i--) putchar(' ');
  123.         if (!rright) fill(line, llen);    /* full justificaton -- fill to llen*/
  124.         puts(line);    /* write the current line */
  125.         firstline = 0;
  126.         strcpy(line, s);
  127.         return;
  128.     }
  129.     if (dbl) strcat(line, " ");    /* space after sentence */
  130.     strcat(line, " ");    /* space after last word */
  131.     strcat(line, s);
  132. }
  133.  
  134. void morepar(char *s) {
  135.     /* compose an input line for a paragraph */
  136.     int i;
  137.     char word[WORDMAX], dummy[WORDMAX];
  138.     while (sscanf(s, "%s%n", word, &i) >= 1) {
  139.         s += i;
  140.         if (word[strlen(word)-1] == '-' &&
  141.             strlen(word) > 1 &&
  142.             word[strlen(word)-2] != '-' &&
  143.             sscanf(s, "%s", dummy) <= 0) {
  144.             /* line ends with hyphenated word */
  145.             strcpy(hword, word);
  146.         }
  147.         else
  148.             emitword(word);
  149.     }
  150. }
  151.  
  152. void endpar(void) {
  153.     /* write out remainder of paragraph */
  154.     if (!ZEROLEN(hword)) {    /* have dangling hyphenated word */
  155.         nohyph = 0;
  156.         morepar(hword);
  157.         nohyph = 1;
  158.         hword[0] = '\0';
  159.     }
  160.     if (wproc) { /* special case for Word Processing output */
  161.         puts(line);
  162.         return;
  163.     }
  164.     if (!ZEROLEN(line)) {
  165.         int i = firstline ? indent : body;
  166.         while (i--) putchar(' ');
  167.         puts(line);
  168.     }
  169. }
  170.  
  171. void startpar(char *s) {
  172.     /* compose first line of paragraph */
  173.     firstline = 1;
  174.     line[0] = 0;
  175.     morepar(s);
  176. }
  177.  
  178. void main(int argc, char **argv) {
  179.     char lbuf[LINEMAX];            /* current line */
  180.     char nbuf[LINEMAX];            /* next line */
  181.     char *eofchk;
  182.  
  183.     fprintf(stderr, "JUSTIFY -- formats text. Copyright 1993 by Tom Almy.\n"
  184.                     "May be freely used and distributed as long as no charge\n"
  185.                     "is made beyond distribution costs and program is not modified.\n");
  186.  
  187.     if (argc < 2) usage();
  188.     else {
  189.         columns = abs(atoi(argv[1]));
  190.         if (columns==0) usage();
  191.         if (argc > 2) {
  192.             char *cp = argv[2];
  193.             while (*cp) switch (*cp++) {
  194.             case 'b': hindent = 1; break;
  195.             case 'f': fullpar = 1; hindent = 1; break;
  196.             case 'd': dblank = 1; break;
  197.             case 'i': iblank = 1; break;
  198.             case 't': indpar = 1; break;
  199.             case 'o': indbod = 1; break;
  200.             case 'h': nohyph = 1; break;
  201.             case 'r': rright = 1; break;
  202.             case 's': dspace = 1; break;
  203.             case 'w': wproc = 1; break;
  204.             default: usage();
  205.             }
  206.             if (argc !=  indpar + indbod  + 3) usage();
  207.             if (indpar && (indent = abs(atoi(argv[3]))) == 0)
  208.                 usage();
  209.             if (indbod && (body = abs(atoi(argv[indpar? 4 : 3]))) == 0)
  210.                 usage();
  211.         }
  212.     }
  213.  
  214.     if (fgets(lbuf, LINEMAX, stdin) == NULL) return;
  215.     trim(lbuf);
  216.  
  217.     while (fgets(nbuf, LINEMAX, stdin) != NULL) { /* figure next action */
  218.         trim(nbuf);
  219.         if (BLANK(lbuf)) {    /* current is blank */
  220.             strcpy(lbuf, nbuf);    /* copy next into current */
  221.             fputs("\n", stdout);    /* emit a blank line */
  222.             continue;
  223.         }
  224.         if ((fullpar && (!INDENTED(lbuf) || BLANK(nbuf))) ||
  225.             /*Full indented body text;line is not indented or next line blank*/
  226.             (!fullpar && hindent && (INDENTED(lbuf) || !INDENTED(nbuf))) ||
  227.              /* Hanging indent and line is is indented or next line is not
  228.                indented (or is blank) */
  229.             (!hindent && (INDENTED(nbuf) || BLANK(nbuf))))
  230.             /* next is blank or indented */ {
  231.             fputs(lbuf, stdout);    /* print line */
  232.             strcpy(lbuf, nbuf);        /* next becomes current */
  233.             continue;
  234.         }
  235.         /* We have a paragraph to format */
  236.         startpar(lbuf);
  237.         do {
  238.             morepar(nbuf);
  239.         } while ((eofchk = fgets(nbuf,LINEMAX,stdin)) != NULL &&
  240.                  trim(nbuf) &&
  241.                ((!INDENTED(nbuf)) ^ hindent) && !BLANK(nbuf));
  242.         endpar();
  243.         if (eofchk == NULL) return;    /* finished at end of paragraph */
  244.         if (iblank) fputs("\n",stdout);    /* optional insert of blank line */
  245.         strcpy(lbuf, nbuf);    /* next becomes current */
  246.         if (dblank && BLANK(lbuf)) { /* optional delete of blank line */
  247.             if (fgets(lbuf, LINEMAX, stdin) == NULL) return; /* End of file */
  248.             trim(lbuf);
  249.         }
  250.     }
  251.     fputs(lbuf, stdout);    /* file ends with blank line or single line */
  252. }
  253.